//
// Created by Luhang on 2023/10/15/015.
//

#ifndef LOGPROJECT_BUFFER_H
#define LOGPROJECT_BUFFER_H

#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <cassert>

namespace LuLog{
    #define BUFFER_DEFAULT_SIZE (1 * 1024 * 1024)
    #define BUFFER_INCREMENT_SIZE (1 * 1024 * 1024)
    #define BUFFER_THRESHOLD_SIZE (8 * 1024 * 1024)

    class Buffer{
    public:
        Buffer():_readerIdx(0), _writerIdx(0), _v(BUFFER_DEFAULT_SIZE){}
        bool empty(){
            return _readerIdx == _writerIdx;
        }
        size_t readableSize(){
            return _writerIdx - _readerIdx;
        }
        size_t writableSize(){
            return _v.size() - _writerIdx;
        }
        void push(const char *data, size_t len){
            //assert(len <= writableSize());
            ensureEnoughSpace(len);
            std::copy(data, data + len, &_v[_writerIdx]);
            _writerIdx += len;
        }
        void pop(size_t len){
            _readerIdx += len;
            assert(_readerIdx <= _writerIdx);
        }
        const char *begin(){
            return &_v[_readerIdx];
        }
        void swap(Buffer &buf){
            _v.swap(buf._v);
            std::swap(_readerIdx, buf._readerIdx);
            std::swap(_writerIdx, buf._writerIdx);
        }
        void reset(){
            _readerIdx = _writerIdx = 0;
        }
        void moveReader(size_t len){
            assert(len <= readableSize());
            _readerIdx += len;
        }
    protected:
        void ensureEnoughSpace(size_t len){
            if(len <= writableSize())
                return;
            size_t newCapacity;
            //小于阈值则翻倍增长
            if(_v.size() < BUFFER_THRESHOLD_SIZE)
                newCapacity = _v.size() * 2 + len;
            //否则线性增长
            else
                newCapacity = _v.size() + BUFFER_INCREMENT_SIZE + len;
            _v.resize(newCapacity);
        }

    private:
        size_t _readerIdx;
        size_t _writerIdx;
        std::vector<char> _v;
    };
}
#endif //LOGPROJECT_BUFFER_H
